﻿using System;
using System.Collections.Generic;
using System.Linq;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Linq;
using Neturion.Dados;
using Neturion.IRepositorios;

namespace Neturion.Repositorios
{
    public class RepositorioAgencia : IRepositorioAgencia
    {
        public Agencia Inserir(Agencia agencia)
        {
            agencia.FimVigenciaAgencia = agencia.FimVigenciaAgencia.HasValue
                                                ? agencia.FimVigenciaAgencia.Value.Date
                                                : agencia.FimVigenciaAgencia;
            agencia.InicioVigenciaAgencia = agencia.InicioVigenciaAgencia.HasValue
                                                ? agencia.InicioVigenciaAgencia.Value.Date
                                                : agencia.InicioVigenciaAgencia;
            foreach (ContaBanco contaBanco in agencia.ListaContasBanco)
            {
                contaBanco.Agencia = agencia;
            }

            GerenciadorBDConfigs.Instance.SessaoAtual().Save(agencia);
            return agencia;
        }

        public Agencia Atualizar(Agencia agencia)
        {
            Agencia tmpAgencia = ObterPorId(agencia.AgenciaId);
            // Atribuicao dos valores do objeto da memoria para o objeto obtido no banco de dados
            tmpAgencia.NumeroAgencia = agencia.NumeroAgencia;
            tmpAgencia.Gerente = agencia.Gerente;
            tmpAgencia.Banco = agencia.Banco;
            tmpAgencia.Codigo = agencia.Codigo;
            tmpAgencia.FimVigenciaAgencia = agencia.FimVigenciaAgencia.HasValue
                                                ? agencia.FimVigenciaAgencia.Value.Date
                                                : agencia.FimVigenciaAgencia;
            tmpAgencia.InicioVigenciaAgencia = agencia.InicioVigenciaAgencia.HasValue
                                                ? agencia.InicioVigenciaAgencia.Value.Date
                                                : agencia.InicioVigenciaAgencia;
            tmpAgencia.ObservacaoAgencia = agencia.ObservacaoAgencia;
            tmpAgencia.Pessoa = agencia.Pessoa;
            
            tmpAgencia.ListaContasBanco.Clear();
            foreach (ContaBanco contaBanco in agencia.ListaContasBanco)
            {
                tmpAgencia.AdicionarContaBanco(contaBanco);
            }

            GerenciadorBDConfigs.Instance.SessaoAtual().Merge(tmpAgencia);
            return tmpAgencia;
        }

        public void Excluir(Agencia agencia)
        {
            GerenciadorBDConfigs.Instance.SessaoAtual().Delete(agencia);
        }

        public IList<Agencia> ObterTodos()
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Agencia));
            return criteria.List<Agencia>() as List<Agencia>;
        }

        public IList<Agencia> ObterTodos(int inicio, int quantidade, int quantidadeMinima, string codigo, string numeroAgencia,
                                Pessoa gerente, Banco banco, DateTime? inicioVigenciaDe, DateTime? inicioVigenciaAte,
                                DateTime? fimVigenciaDe, DateTime? fimVigenciaAte)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Agencia))
               .SetFirstResult(inicio).SetMaxResults(quantidade);

            if (!string.IsNullOrEmpty(codigo))
            {
                criteria.Add(Restrictions.Eq("Codigo", codigo));
            }

            if (!string.IsNullOrEmpty(numeroAgencia))
            {
                criteria.Add(Restrictions.Eq("NumeroAgencia", numeroAgencia));
            }

            if (gerente != null)
            {
                criteria.Add(Restrictions.Eq("Gerente", gerente));
            }

            if (banco != null)
            {
                criteria.Add(Restrictions.Eq("Banco", banco));
            }

            if (inicioVigenciaDe.HasValue)
            {
                criteria.Add(inicioVigenciaAte.HasValue
                    ? Restrictions.Between("InicioVigencia", inicioVigenciaDe.Value.Date, inicioVigenciaAte.Value.Date)
                    : Restrictions.Eq("InicioVigencia", inicioVigenciaDe.Value.Date));
            }

            if (fimVigenciaDe.HasValue)
            {
                criteria.Add(fimVigenciaAte.HasValue
                    ? Restrictions.Between("FimVigencia", fimVigenciaDe.Value.Date, fimVigenciaAte.Value.Date)
                    : Restrictions.Eq("FimVigencia", fimVigenciaDe.Value.Date));
            }

            return criteria.List<Agencia>() as List<Agencia>;
        }

        public Agencia ObterPorId(int id)
        {
            return GerenciadorBDConfigs.Instance.SessaoAtual().Get<Agencia>(id);
        }

        public IList<Agencia> ObterAgenciaPorNumero(string numero)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Agencia))
                .Add(Restrictions.Like("NumeroAgencia", numero, MatchMode.Anywhere));

            return criteria.List<Agencia>() as List<Agencia>;
        }

        public int ObterUltimoIdCodigoInteiro()
        {
            string[] literal = new string[] 
                {"a","b","c","d","e","f","g","h","i","j"
                ,"l","m","n","o","p","q","r","s","t","u","v","x","z","y"
                ,"w"};

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Agencia)).SetMaxResults(1);

            for (int i = 0; i <= literal.Length - 1; i++)
            {
                criteria.Add(Restrictions.Not(Restrictions.Like("Codigo", literal[i], MatchMode.Anywhere)));
            }

            criteria.AddOrder(Order.Desc("AgenciaId"));


            Agencia agencia = criteria.UniqueResult<Agencia>();
            int ultimoCodigo = agencia != null ? agencia.AgenciaId : 0;

            return ultimoCodigo;
        }

        public Agencia ObterPorCodigo(string codigo)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Agencia))
                .Add(Restrictions.Eq("Codigo", codigo));

            return criteria.UniqueResult<Agencia>() as Agencia;
        }
    }
}